import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { useAtomValue, useSetAtom } from 'jotai';
import {
  serverMapCurrentTargetDataAtom,
  currentServerAtom,
  currentServerAgentIdAtom,
  serverMapDataAtom,
  serverMapCurrentTargetAtom,
} from '@pinpoint-fe/ui/src/atoms';
import {
  END_POINTS,
  GetServerMap,
  SearchApplication,
  BASE_PATH,
  GetHistogramStatistics,
} from '@pinpoint-fe/ui/src/constants';
import {
  convertParamsToQueryString,
  getParsedDate,
  getInspectorPath,
} from '@pinpoint-fe/ui/src/utils';
import { useSearchParameters, useServerMapLinkedData } from '@pinpoint-fe/ui/src/hooks';
import { queryFn } from '@pinpoint-fe/ui/src/hooks/api/reactQueryHelper';
import { ServerList as SL, ServerListProps, Button, ServerListSkeleton } from '@pinpoint-fe/ui';
import { upperCase } from 'lodash';

export interface ServerListFetcherProps extends ServerListProps {
  nodeStatistics?: GetHistogramStatistics.Response;
  disableFetch?: boolean;
}

export const ServerListFetcher = ({ nodeStatistics, disableFetch }: ServerListFetcherProps) => {
  const { searchParameters } = useSearchParameters();
  const currentTarget = useAtomValue(serverMapCurrentTargetAtom);
  const currentTargetData = useAtomValue(serverMapCurrentTargetDataAtom) as GetServerMap.NodeData;
  const setCurrentServer = useSetAtom(currentServerAtom);
  const currentServerAgent = useAtomValue(currentServerAgentIdAtom);
  const serverMapData = useAtomValue(serverMapDataAtom);
  const serverMapLinkedData = useServerMapLinkedData({
    serverMapData: serverMapData?.applicationMapData as GetServerMap.ApplicationMapData,
    currentTargetData,
  });
  const applicationPairs = {
    from: serverMapLinkedData?.from.map(({ applicationName, serviceTypeCode }) => [
      applicationName,
      serviceTypeCode,
    ]),
    to: serverMapLinkedData?.to.map(({ applicationName, serviceTypeCode }) => [
      applicationName,
      serviceTypeCode,
    ]),
  };

  const queryParams: SearchApplication.Parameters = {
    application: currentTargetData?.applicationName,
    serviceTypeName: currentTargetData?.serviceType,
    serviceTypeCode: currentTargetData?.serviceTypeCode,
    sortBy: 'AGENT_ID_ASC',
    from: getParsedDate(searchParameters.from).getTime(),
    to: getParsedDate(searchParameters.to).getTime(),
    applicationPairs: JSON.stringify(applicationPairs),
  };

  const queryString = React.useMemo(() => {
    if (
      queryParams.from &&
      queryParams.to &&
      queryParams.application &&
      queryParams.sortBy &&
      queryParams.serviceTypeCode &&
      queryParams.applicationPairs
    ) {
      return '?' + convertParamsToQueryString(queryParams);
    }
    return '';
  }, [queryParams]);

  const { data, isLoading } = useQuery<SearchApplication.Response | null>({
    queryKey: [END_POINTS.SEARCH_APPLICATION, queryString],
    queryFn: queryFn(`${END_POINTS.SEARCH_APPLICATION}${queryString}`),
    enabled: !!queryString && !disableFetch,
  });

  React.useEffect(() => {
    if (data) {
      const servers = getServers();
      setCurrentServer(servers?.[0]);
    }
  }, [data, currentTarget]);

  const getServers = () => {
    return data?.reduce<SearchApplication.Instance[]>((prev, curr) => {
      curr.instancesList.forEach((instance) => {
        prev.push(instance);
      });
      return prev;
    }, []);
  };

  const handleClickItem: ServerListProps['onClick'] = (instance) => {
    setCurrentServer(instance);
  };

  const renderGroupName: ServerListProps['groupNameRenderer'] = (application) => {
    return (
      <>
        {application?.groupName === 'Container' ? (
          <div className="flex-1 truncate">{application.groupName}</div>
        ) : (
          <>
            <div className="flex-1 truncate">{application.groupName}</div>
            {application?.instancesList?.[0]?.linkList?.map((link, index) => {
              return (
                <LinkButton key={index}>
                  <a href={link.linkURL} target={'_blank'}>
                    {upperCase(link.linkName)}
                  </a>
                </LinkButton>
              );
            })}
          </>
        )}
      </>
    );
  };

  const renderItem: ServerListProps['itemRenderer'] = (application, instance) => {
    return (
      <>
        <div className="flex-1 truncate">{instance?.agentName || instance.agentId}</div>{' '}
        {application?.groupName === 'Container'
          ? instance?.linkList?.map((link, index) => {
              return (
                <LinkButton key={index}>
                  <a href={link.linkURL} target={'_blank'}>
                    {upperCase(link.linkName)}
                  </a>
                </LinkButton>
              );
            })
          : null}
      </>
    );
  };

  if (isLoading) {
    return (
      <div className="flex h-full">
        <ServerListSkeleton className="h-full border-t border-r" />
      </div>
    );
  }

  return (
    <SL
      data={data || []}
      className={'border-t border-r bg-neutral-100'}
      statistics={nodeStatistics}
      selectedId={currentServerAgent}
      onClick={handleClickItem}
      groupNameRenderer={renderGroupName}
      itemRenderer={renderItem}
      onClickInspectorLink={(agentId) => {
        window.open(
          `${BASE_PATH}${getInspectorPath(currentTargetData, searchParameters)}&agentId=${agentId}`,
        );
      }}
    ></SL>
  );
};

const LinkButton = ({ children }: { children: React.ReactNode }) => {
  return (
    <Button variant={'outline'} className="h-5 px-1 text-xs border border-primary" asChild>
      {children}
    </Button>
  );
};
